<?php

namespace App\Http\Controllers\Storage;

use App\Http\Controllers\Controller;
use OSS\OssClient;
use OSS\Core\OssException;
use DateTime;

class OSSUploadController extends Controller
{
    private $client;
    private $config;

    /**
     * Create a new controller instance.
     */
    public function __construct()
    {
        $this->config = config('oss');
        try {
            $this->client = new OssClient($this->config['access_key_id'], $this->config['access_key_secret'], $this->config['endpoint']);
            # $this->client->setTimeout($this->config['time_out']);
            # $this->client->setConnectTimeout($this->config['connect_time_out']);
        } catch (OssException $e) {
            return $this->error('1001', ['msg' => $e->getMessage()]);
        }
    }

    /**
     * 国际标准时 GMT ISO 8601
     * @param $time
     * @return string
     */
    private function GMT($time)
    {
        $time = date("c", $time);
        $datetime = new DateTime($time);
        $expiration = $datetime->format(DateTime::ISO8601);
        $pos = strpos($expiration, '+');
        $expiration = substr($expiration, 0, $pos);
        return $expiration."Z";
    }

    public function sign() {
        $expire = 30; # 设置该policy超时时间是10s. 即这个policy过了这个有效时间，将不能访问
        $dir = 'user-dir/'; # 这个参数是设置用户上传指定的前缀
        //$callback = url('storage/oss/upload/callback');
        $callback = 'http://art.9ebo.com/callback.php';
        # 有效生命周期
        $end = time() + $expire;
        $expiration = $this->GMT($end);
        # 上传限制
        $conditions = [];
        # 最大文件大小
        $conditions[] = [
            0 => 'content-length-range',
            1 => 0,
            2 => 1048576000
        ];
        # 表示用户上传的数据,必须是以$dir开始, 不然上传会失败,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录
        $conditions[] = [
            0 => 'starts-with',
            1 => '$key',
            2 => $dir
        ];
        # 回调参数
        $callbackString = json_encode([
            'callbackUrl' => $callback,
            'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}',
            'callbackBodyType' => "application/x-www-form-urlencoded"
        ]);
        # 返回签名
        $response = [];
        $policy = json_encode([
            'expiration' => $expiration,
            'conditions' => $conditions
        ]);
        $response['id'] = $this->config['access_key_id'];
        $response['key'] = $dir;
        $response['host'] = 'http://' . $this->config['bucket'] . '.' . $this->config['endpoint'];
        $response['policy'] = base64_encode($policy);
        $response['signature'] = base64_encode(hash_hmac('sha1', $response['policy'], $this->config['access_key_secret'], true));
        $response['expire'] = $end;
        $response['callback'] = base64_encode($callbackString);
        return $response;
    }

    public function callback()
    {
        $authorization = ''; # OSS的签名
        $pubKeyUrl = ''; # 公钥url
        # 注意：如果要使用HTTP_AUTHORIZATION头，你需要先在apache或者nginx中设置rewrite，以apache为例，修改
        # 配置文件/etc/httpd/conf/httpd.conf(以你的apache安装路径为准)，在DirectoryIndex index.php这行下面增加以下两行
        # RewriteEngine On
        # RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
        if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
            $authorization = base64_decode($_SERVER['HTTP_AUTHORIZATION']);
        }
        if (isset($_SERVER['HTTP_X_OSS_PUB_KEY_URL'])) {
            $pubKeyUrl = $_SERVER['HTTP_X_OSS_PUB_KEY_URL'];
        }
        if (empty($authorization) || empty($pubKeyUrl)) {
            abort(403, 'Forbidden');
        }
        # 获取公钥
        $pubKey = curlGet($pubKeyUrl);
        if (empty($pubKey)) {
            abort(403, 'Forbidden');
        }
        # 获取回调body
        $body = file_get_contents('php://input');
        # 拼接待签名字符串
        $authStr = '';
        $path = $_SERVER['REQUEST_URI'];
        $pos = strpos($path, '?');
        if ($pos === false) {
            $authStr = urldecode($path)."\n".$body;
        } else {
            $authStr = urldecode(substr($path, 0, $pos)).substr($path, $pos, strlen($path) - $pos)."\n".$body;
        }
        # 验证签名
        $result = openssl_verify($authStr, $authorization, $pubKey, OPENSSL_ALGO_MD5);
        if ($result == 1) {
            return ['Status' => 'ok'];
        } else {
            abort(403, 'Forbidden');
        }
    }
}
